package com.yanqu.road.server.gameplayer.module.banquet;

import com.alibaba.fastjson.JSON;
import com.yanqu.road.entity.DataStatus;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.banquet.*;
import com.yanqu.road.entity.banquet.cross.CrossFeastPartyTempData;
import com.yanqu.road.entity.banquet.invitation.BanquetCrossInvitation;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.LogBanquetIntegral;
import com.yanqu.road.entity.servercenter.TitleInfo;
import com.yanqu.road.logic.bussiness.player.UserBanquetBussiness;
import com.yanqu.road.logic.bussiness.player.UserBanquetInvitationBussiness;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.message.YanQuMessage;
import com.yanqu.road.pb.banquet.BanquetProto;
import com.yanqu.road.pb.banquet.CrossBanquetProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.activity.ActivityModule;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.gameplayer.module.player.AttributeModule;
import com.yanqu.road.server.gameplayer.module.player.BeautyModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.PreReduceModule;
import com.yanqu.road.server.logic.activity.BaseActivityData;
import com.yanqu.road.server.manger.CrossMarriageGroupMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.activity.ActivityMgr;
import com.yanqu.road.server.manger.activity.NormalActivityMgr;
import com.yanqu.road.server.manger.banquet.BanquetConfigMgr;
import com.yanqu.road.server.manger.banquet.BanquetMgr;
import com.yanqu.road.server.manger.banquet.CrossBanquetAutoOpenMgr;
import com.yanqu.road.server.manger.banquet.CrossBanquetMgr;
import com.yanqu.road.server.manger.config.TitleMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.log.LogMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.pb.BanquetPb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.ConfigHelper;
import com.yanqu.road.utils.UUIDHelper;
import com.yanqu.road.utils.YanQuMessageUtils;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class BanquetModule extends GeneralModule {


    //婚宴的个数，每个人开的前几个婚宴要用机器人填满座位
    private int normalBanquetNum = 0;

    public BanquetModule(GamePlayer player) {
        super(player);
    }

    //判断是不是要给宴会机器人满座
    public boolean isBanquetNormalFullSeat() {
        return normalBanquetNum < GameConfig.BANQUET_MARRY_FULL_SEAT_NUM;
    }

    public void addBanquetNormalNum() {
        normalBanquetNum++;
    }

    public void addBanquetNormalNum(int addNum) {
        normalBanquetNum = normalBanquetNum + addNum;
    }

    public int getNormalBanquetNum() {
        return normalBanquetNum;
    }

    private Map<String, UserBanquetInvitation> allUserBanquetInvitationMap;
    private Map<String, UserBanquetInvitation> userBanquetInvitationMap;

    //本服盛宴和跨服盛宴人气礼
    private Map<String, Map<Integer, UserBanquetFeastReward>> userBanquetFeastRewardMap;

    private Map<String, UserBanquetRecord> userBanquetRecordMap;

    //跨服私人宴會
    private Map<String, UserBanquetRecord> userCrossBanquetRecordMap;

    private Map<Integer, UserBanquetSetting> userBanquetSettingMap;

    @Override
    public boolean loadData() {
        normalBanquetNum = UserBanquetBussiness.getUserBanquetNormalCount(player.getUserId());
        allUserBanquetInvitationMap = UserBanquetInvitationBussiness.getUserBanquetInvitationList(player.getUserId());
        String typeIn = BanquetConfigMgr.getBanquetIdIn(eBanquetType.ServerNormalBanquet.getValue());
        long beginTime = System.currentTimeMillis() - BanquetMgr.RECORD_EXPIRE_TIME;
        int rowMax = GameConfig.BANQUET_RECORD_LIST_MAX;
        userBanquetRecordMap = UserBanquetBussiness.getUserBanquetRecordMap(player.getUserId(), typeIn, beginTime, rowMax);
        String typeInCrossUserBanquet = BanquetConfigMgr.getBanquetIdIn(eBanquetType.CrossUserBanquet.getValue());
        userCrossBanquetRecordMap = UserBanquetBussiness.getUserBanquetRecordMap(player.getUserId(), typeInCrossUserBanquet, beginTime, rowMax);
        removeOverTimeInvitation();

        userBanquetFeastRewardMap = new ConcurrentHashMap<>();
        Map<String, CrossFeastPartyTempData> openFeastBanquetMap = BanquetMgr.getCrossFeastPartyTempDataMap();
        for (CrossFeastPartyTempData banquet : openFeastBanquetMap.values()) {
            userBanquetFeastRewardMap.put(banquet.getBanquetId(), UserBanquetBussiness.getFeastBanquetReward(banquet.getBanquetId(), player.getUserId()));
        }
        //跨服宴会
        Map<String, UserCrossBanquetData> openCrossFeastBanquetMap = CrossBanquetMgr.getBanquetOpen();
        for (UserCrossBanquetData banquet : openCrossFeastBanquetMap.values()) {
            userBanquetFeastRewardMap.put(banquet.getBanquetId(), UserBanquetBussiness.getFeastBanquetReward(banquet.getBanquetId(), player.getUserId()));
        }

        userBanquetSettingMap = UserBanquetBussiness.getUserBanquetSetting(player.getUserId());

        return true;
    }

    //返回玩家的互宴信息
    public List<UserBanquetRelationship> getUserBanquetRelationship() {
        Map<Long, UserBanquetRelationship> recordMap = BanquetMgr.getUserBanquetRelationshipMap(player.getUserId());
        List<UserBanquetRelationship> recordList = new ArrayList<>(recordMap.values());
        recordList.sort(new RelationshipSort());
        if (recordList.size() > GameConfig.BANQUET_RELATIONSHIP_LIST_MAX) {
            int index = recordList.size() - 1;
            for (; index >= GameConfig.BANQUET_RELATIONSHIP_LIST_MAX; index--) {
                recordList.remove(index);
            }
        }
        return recordList;
    }

    public void resetInvitation(String invitationId) {
        UserBanquetInvitation inv = userBanquetInvitationMap.get(invitationId);
        if (inv == null) {
            return;
        }
        inv.setUsed(false);
        log.error("{} open party fail, reset invitationId {}", player.getUserId(), invitationId);
    }

    public int checkFeastReward(String partyId, int rewardId, int type) {
        if (BanquetMgr.isCrossFeastPartyOver(partyId)) {
            return GameErrorCode.E_BANQUET_IS_OVER;
        }
        Map<Integer, UserBanquetFeastReward> infoMap = userBanquetFeastRewardMap.get(partyId);
        if (infoMap == null) {
            infoMap = new ConcurrentHashMap<>();
            userBanquetFeastRewardMap.put(partyId, infoMap);
        }
        if (infoMap.containsKey(rewardId)) {
            return GameErrorCode.E_BANQUET_FEAST_POP_ISGET_REWARD;
        }
        return 0;
    }

    public Property addFeastReward(String partyId, int rewardId,int type) {
        Property reward = new Property();
        Map<Integer, UserBanquetFeastReward> rewardMap = userBanquetFeastRewardMap.get(partyId);
        if (!rewardMap.containsKey(rewardId)) {
            Map<Integer, List<String>> rewardInfoMap = BanquetConfigMgr.getBanquetFeastRewardMap();
            UserBanquetFeastReward rewardInfo = new UserBanquetFeastReward();
            rewardInfo.setBanquetId(partyId);
            rewardInfo.setReward(rewardInfoMap.get(rewardId).get(2));
            rewardInfo.setGetTime(0);
            rewardInfo.setRewardId(rewardId);
            rewardInfo.setType(type);
            rewardInfo.setUserId(getUserId());
            rewardInfo.setInsertOption();
            rewardMap.put(rewardId, rewardInfo);
            rewardMap.get(rewardId).setGetReward(true);
            rewardMap.get(rewardId).setGetTime(System.currentTimeMillis());
            player.getModule(CurrencyModule.class).addCurrency(rewardMap.get(rewardId).getReward(), eLogMoneyType.Banquet, eLogMoneyType.BanquetFeastPopReward);
            reward.addProperty(PropertyHelper.parseStringToProperty(rewardMap.get(rewardId).getReward()));
        }
        return reward;
    }

    public int getAllCrossBanquetPopReward(String banquetId) {

        initCrossBanquetPopRewardList(banquetId);
        UserCrossBanquetData banquet = CrossBanquetMgr.getBanquet(banquetId);
        if (banquet == null || CrossBanquetMgr.isBanquetOver(banquet.getBanquetId())) {
            return GameErrorCode.E_BANQUET_IS_OVER;
        }
        Property reward = new Property();
        Map<Integer, UserBanquetFeastReward> rewardMap = userBanquetFeastRewardMap.get(banquetId);
        Map<Integer, List<String>> rewardInfoMap = BanquetConfigMgr.getCrossBanquetPopRewardMap();
        for (Integer rewardId : rewardInfoMap.keySet()) {
            if (userBanquetFeastRewardMap.get(banquetId).get(rewardId).isGetReward()) {
                continue;
            }
            if (banquet.getUserCount() < Integer.valueOf(rewardInfoMap.get(rewardId).get(1))) {
                continue;
            }
            rewardMap.get(rewardId).setGetReward(true);
            rewardMap.get(rewardId).setGetTime(System.currentTimeMillis());
            player.getModule(CurrencyModule.class).addCurrency(rewardMap.get(rewardId).getReward(), eLogMoneyType.Banquet, eLogMoneyType.BanquetCrossPopReward);
            reward.addProperty(PropertyHelper.parseStringToProperty(rewardMap.get(rewardId).getReward()));
        }
        if (reward.isNothing()) {
            return GameErrorCode.E_BANQUET_NO_REWARD;
        }
        CrossBanquetProto.BanquetGetAllPopRewardResp.Builder resp = CrossBanquetProto.BanquetGetAllPopRewardResp.newBuilder();
        resp.setRet(0);
        resp.setRewards(PropertyHelper.parsePropertyToString(reward));
        player.sendPacket(ClientProtocol.U_BANQUET_CROSU_GET_ALL_REWARD, resp);
        return 0;
    }

    //互宴信息排序
    static class RelationshipSort implements Comparator<UserBanquetRelationship> {
        @Override
        public int compare(UserBanquetRelationship o1, UserBanquetRelationship o2) {
            if (o1.getTo() + o1.getFrom() == o2.getTo() + o2.getFrom()) {
                return 0;
            }
            if (o1.getTo() + o1.getFrom() >= o2.getTo() + o2.getFrom()) {
                return -1;
            }
            return 1;
        }
    }

    //获取人气礼奖励
    public int getCrossBanquetPopReward(String banquetId, int rewardId) {
        initCrossBanquetPopRewardList(banquetId);
        UserCrossBanquetData banquet = CrossBanquetMgr.getBanquet(banquetId);
        if (banquet == null || CrossBanquetMgr.isBanquetOver(banquet.getBanquetId())) {
            return GameErrorCode.E_BANQUET_IS_OVER;
        }
        Map<Integer, UserBanquetFeastReward> rewardMap = userBanquetFeastRewardMap.get(banquetId);
        if (userBanquetFeastRewardMap.get(banquetId).get(rewardId).isGetReward()) {
            return GameErrorCode.E_BANQUET_FEAST_POP_ISGET_REWARD;
        }
        Map<Integer, List<String>> rewardInfoMap = BanquetConfigMgr.getCrossBanquetPopRewardMap();
        if (banquet.getUserCount() < Integer.valueOf(rewardInfoMap.get(rewardId).get(1))) {
            return GameErrorCode.E_BANQUET_FEAST_POP_CANT_REWARD;
        }
        rewardMap.get(rewardId).setGetReward(true);
        rewardMap.get(rewardId).setGetTime(System.currentTimeMillis());
        player.getModule(CurrencyModule.class).addCurrency(rewardMap.get(rewardId).getReward(), eLogMoneyType.Banquet, eLogMoneyType.BanquetCrossPopReward);
        return 0;
    }

    public int getUserBanquetFeastReward(String banquetId, int rewardId) {
        initUserBanquetFeastRewardList(banquetId);
        UserBanquetData banquet = BanquetMgr.getBanquet(banquetId);
        if (banquet == null || BanquetMgr.isBanquetOver(banquet.getBanquetId())) {
            return GameErrorCode.E_BANQUET_IS_OVER;
        }
        Map<Integer, UserBanquetFeastReward> rewardMap = userBanquetFeastRewardMap.get(banquetId);
        if (userBanquetFeastRewardMap.get(banquetId).get(rewardId).isGetReward()) {
            return GameErrorCode.E_BANQUET_FEAST_POP_ISGET_REWARD;
        }
        Map<Integer, List<String>> rewardInfoMap = BanquetConfigMgr.getBanquetFeastRewardMap();
        if (banquet.getUserCount() < Integer.valueOf(rewardInfoMap.get(rewardId).get(1))) {
            return GameErrorCode.E_BANQUET_FEAST_POP_CANT_REWARD;
        }
        rewardMap.get(rewardId).setGetReward(true);
        rewardMap.get(rewardId).setGetTime(System.currentTimeMillis());
        player.getModule(CurrencyModule.class).addCurrency(rewardMap.get(rewardId).getReward(), eLogMoneyType.Banquet, eLogMoneyType.BanquetFeastPopReward);
        return 0;
    }

    public void initUserBanquetFeastRewardList(String banquetId) {
        Map<Integer, UserBanquetFeastReward> infoMap = new ConcurrentHashMap<>();
        if (!BanquetMgr.isBanquetOver(banquetId)) {
            UserBanquetData banquet = BanquetMgr.getBanquet(banquetId);
            if (userBanquetFeastRewardMap.containsKey(banquetId)) {
                infoMap = userBanquetFeastRewardMap.get(banquetId);
            }
            Map<Integer, List<String>> rewardInfoMap = BanquetConfigMgr.getBanquetFeastRewardMap();
            for (Integer rewardId : rewardInfoMap.keySet()) {
                if (!infoMap.containsKey(rewardId)) {
                    UserBanquetFeastReward rewardInfo = new UserBanquetFeastReward();
                    rewardInfo.setBanquetId(banquetId);
                    rewardInfo.setGetReward(false);
                    rewardInfo.setReward(rewardInfoMap.get(rewardId).get(2));
                    rewardInfo.setGetTime(0);
                    rewardInfo.setRewardId(rewardId);
                    rewardInfo.setType(banquet.getType());
                    rewardInfo.setUserId(getUserId());
                    rewardInfo.setInsertOption();
                    infoMap.put(rewardId, rewardInfo);
                }
            }
            userBanquetFeastRewardMap.put(banquetId, infoMap);
        }
    }

    public void initCrossBanquetPopRewardList(String banquetId) {
        Map<Integer, UserBanquetFeastReward> infoMap = new ConcurrentHashMap<>();
        if (!CrossBanquetMgr.isBanquetOver(banquetId)) {
            UserCrossBanquetData banquet = CrossBanquetMgr.getBanquet(banquetId);
            if (userBanquetFeastRewardMap.containsKey(banquetId)) {
                infoMap = userBanquetFeastRewardMap.get(banquetId);
            }
            Map<Integer, List<String>> rewardInfoMap = BanquetConfigMgr.getCrossBanquetPopRewardMap();
            for (Integer rewardId : rewardInfoMap.keySet()) {
                if (!infoMap.containsKey(rewardId)) {
                    UserBanquetFeastReward rewardInfo = new UserBanquetFeastReward();
                    rewardInfo.setBanquetId(banquetId);
                    rewardInfo.setGetReward(false);
                    rewardInfo.setReward(rewardInfoMap.get(rewardId).get(2));
                    rewardInfo.setGetTime(0);
                    rewardInfo.setRewardId(rewardId);
                    rewardInfo.setType(banquet.getType());
                    rewardInfo.setUserId(getUserId());
                    rewardInfo.setInsertOption();
                    infoMap.put(rewardId, rewardInfo);
                }
            }
            userBanquetFeastRewardMap.put(banquetId, infoMap);
        }
    }

    //获取本服盛宴的人气礼领奖列表登陸的時候所有的同步下去
    public Map<String, Map<Integer, UserBanquetFeastReward>> getUserBanquetFeastRewardList() {
        Map<String, Map<Integer, UserBanquetFeastReward>> res = new ConcurrentHashMap<>();
      /*  Map<String, UserBanquetData> banquets = BanquetMgr.getBanquetOpen(eBanquetType.ServerFeastBanquet.getValue());
        for (String banquetId : banquets.keySet()) {
            initUserBanquetFeastRewardList(banquetId);
            res.put(banquetId, userBanquetFeastRewardMap.get(banquetId));
        }*/
        for (Map.Entry<String, Map<Integer, UserBanquetFeastReward>> entry : userBanquetFeastRewardMap.entrySet()) {
            String partyId = entry.getKey();
            Map<Integer, UserBanquetFeastReward> value = entry.getValue();
            res.put(partyId, value);
        }
        return res;
    }

    //同步一个活動的人氣禮
    public Map<String, Map<Integer, UserBanquetFeastReward>> getUserBanquetFeastReward(UserBanquetData banquetData) {
        Map<String, Map<Integer, UserBanquetFeastReward>> res = new ConcurrentHashMap<>();
        initUserBanquetFeastRewardList(banquetData.getBanquetId());
        res.put(banquetData.getBanquetId(), userBanquetFeastRewardMap.get(banquetData.getBanquetId()));
        return res;
    }

    public Map<String, Map<Integer, UserBanquetFeastReward>> getCrossBanquetPopRewardList() {
        Map<String, Map<Integer, UserBanquetFeastReward>> res = new ConcurrentHashMap<>();
        Map<String, UserCrossBanquetData> banquets = CrossBanquetMgr.getBanquetOpen();
        List<String> list = new ArrayList<>();
        for (UserCrossBanquetData data : banquets.values()) {
            int type = data.getType();
            if (BanquetConfigMgr.isCrossBanquet(type)) {
                list.add(data.getBanquetId());
            }
        }
        for (String banquetId :list) {
            initCrossBanquetPopRewardList(banquetId);
            res.put(banquetId, userBanquetFeastRewardMap.get(banquetId));
        }
        return res;
    }

    public Map<String, Map<Integer, UserBanquetFeastReward>> getCrossBanquetPopReward(UserCrossBanquetData banquetData) {
        Map<String, Map<Integer, UserBanquetFeastReward>> res = new ConcurrentHashMap<>();
        initCrossBanquetPopRewardList(banquetData.getBanquetId());
        res.put(banquetData.getBanquetId(), userBanquetFeastRewardMap.get(banquetData.getBanquetId()));
        return res;
    }

    public Map<Integer, UserBanquetFeastReward> getCrossBanquetPopRewardList(String banquetId) {
        initCrossBanquetPopRewardList(banquetId);
        return userBanquetFeastRewardMap.get(banquetId);
    }


    public boolean isIntegralEnough(long integral) {
        if (integral <= 0) {
            return false;
        }
        AttributeModule attributeModule = player.getModule(AttributeModule.class);
        BigInteger preReduceValue = player.getModule(PreReduceModule.class).getPreReduceItemMap().get(GameConfig.BANQUET_INTEGRAL);
        if (null == preReduceValue) {
            preReduceValue = BigInteger.ZERO;
        }
        long temp = preReduceValue.longValue();
        if (attributeModule.getAttribute(ePlayerAttrType.BanquetIntegral) + temp < integral) {
            return false;
        }
        return true;
    }

    public boolean addPopularity(long popularity, eLogMoneyType master, eLogMoneyType son) {
        if (popularity <= 0) {
            return false;
        }
        AttributeModule attributeModule = player.getModule(AttributeModule.class);
        long oldPopularity = attributeModule.getAttribute(ePlayerAttrType.BanquetPopularity);
        attributeModule.setAttribute(ePlayerAttrType.BanquetPopularity, oldPopularity + popularity);
        AutoLogMgr.add(new LogBanquetIntegral(player.getUserId(), oldPopularity, oldPopularity + popularity, popularity, master.getValue(), son.getValue()));
        return true;
    }

    public boolean addIntegral(long integral, eLogMoneyType master, eLogMoneyType son) {
        if (integral <= 0) {
            return false;
        }
        AttributeModule attributeModule = player.getModule(AttributeModule.class);
        long oldIntegral = attributeModule.getAttribute(ePlayerAttrType.BanquetIntegral);
        attributeModule.setAttribute(ePlayerAttrType.BanquetIntegral, oldIntegral + integral);
        AutoLogMgr.add(new LogBanquetIntegral(player.getUserId(), oldIntegral, oldIntegral + integral, integral, master.getValue(), son.getValue()));
        return true;
    }

    public boolean removeIntegral(long integral, eLogMoneyType master, eLogMoneyType son) {
        if (integral <= 0) {
            return false;
        }
        AttributeModule attributeModule = player.getModule(AttributeModule.class);
        if (attributeModule.getAttribute(ePlayerAttrType.BanquetIntegral) < integral) {
            return false;
        }
        long oldIntegral = attributeModule.getAttribute(ePlayerAttrType.BanquetIntegral);
        attributeModule.setAttribute(ePlayerAttrType.BanquetIntegral, oldIntegral - integral);
        AutoLogMgr.add(new LogBanquetIntegral(player.getUserId(), oldIntegral, oldIntegral - integral, -integral, master.getValue(), son.getValue()));
        return true;
    }

    public boolean removeIntegralToNegative(long integral, eLogMoneyType master, eLogMoneyType son) {
        if (integral <= 0) {
            return false;
        }
        AttributeModule attributeModule = player.getModule(AttributeModule.class);
        long oldIntegral = attributeModule.getAttribute(ePlayerAttrType.BanquetIntegral);
        attributeModule.setAttribute(ePlayerAttrType.BanquetIntegral, oldIntegral - integral);
        AutoLogMgr.add(new LogBanquetIntegral(player.getUserId(), oldIntegral, oldIntegral - integral, -integral, master.getValue(), son.getValue()));
        return true;
    }

    //获取用户的记录列表
    public List<UserBanquetRecord> userBanquetRecordList(int banquetType) {
        ActivityInfo activityInfo = NormalActivityMgr.getExistCrossBanquetRankActivity();
        Map<String, UserBanquetRecord> typeRecordTypeMap = new ConcurrentHashMap<>();
        Map<String, UserBanquetRecord> recordMap = new ConcurrentHashMap<>();
        if (eBanquetType.ServerNormalBanquet.getValue() == banquetType) {
            recordMap = userBanquetRecordMap;
        } else if (eBanquetType.CrossUserBanquet.getValue() == banquetType) {
            recordMap = userCrossBanquetRecordMap;
        }
        for (UserBanquetRecord record : recordMap.values()) {
            if (BanquetMgr.isBanquetType(record.getType(), banquetType)) {
                if (eBanquetType.CrossUserBanquet.getValue() == banquetType) {
                    if (activityInfo != null && record.getOpenTime() / 1000 > activityInfo.getBeginShowTime() && record.getOpenTime() / 1000 < activityInfo.getEndShowTime()) {
                        typeRecordTypeMap.put(record.getBanquetId(), record);
                    }
                } else {
                    typeRecordTypeMap.put(record.getBanquetId(), record);
                }
            }
        }
        List<UserBanquetRecord> recordList = new ArrayList<>(typeRecordTypeMap.values());
        recordList.sort(new RecordSort());
        if (recordList.size() > GameConfig.BANQUET_RECORD_LIST_MAX) {
            int index = recordList.size() - 1;
            for (; index >= GameConfig.BANQUET_RECORD_LIST_MAX; index--) {
                recordList.remove(index);
            }
        }
        return recordList;
    }

    static class RecordSort implements Comparator<UserBanquetRecord> {
        @Override
        public int compare(UserBanquetRecord o1, UserBanquetRecord o2) {
            if (o1.getOpenTime() == o2.getOpenTime()) {
                return 0;
            }
            if (o1.getOpenTime() >= o2.getOpenTime()) {
                return -1;
            }
            return 1;
        }
    }

    //新增宴會記錄
    public void addBanquetRecord(UserBanquetData userBanquetData) {
        UserBanquetRecord userBanquetRecord = new UserBanquetRecord();
        userBanquetRecord.setBanquetId(userBanquetData.getBanquetId());
        userBanquetRecord.setType(userBanquetData.getType());
        userBanquetRecord.setUserId(userBanquetData.getUserId());
        userBanquetRecord.setRecord(JSON.toJSONString(userBanquetData));
        userBanquetRecord.setOpenTime(userBanquetData.getOpenTime());
        userBanquetRecord.setOverTime(userBanquetData.getOverTime());
        userBanquetRecord.setMemberCount(userBanquetData.getUserCount());
        addBanquetRecord(userBanquetRecord);
    }

    public void addBanquetRecord(UserBanquetRecord userBanquetRecord) {
        userBanquetRecord.setInsertOption();
        if (BanquetConfigMgr.isServerFeastBanquet(userBanquetRecord.getType())) {
            BanquetMgr.addFeastBanquetRecord(userBanquetRecord);
        }else {
            userBanquetRecordMap.put(userBanquetRecord.getBanquetId(), userBanquetRecord);
        }
    }

    //跨服私人宴会日志
    public void addCrossUserBanquetRecord(UserBanquetRecord userBanquetRecord) {
        userBanquetRecord.setInsertOption();
        userCrossBanquetRecordMap.put(userBanquetRecord.getBanquetId(), userBanquetRecord);
    }

    //校验请帖是不是过期或者被使用
    public boolean checkUserInvitation(String invitationId, int type) {
        if (!userBanquetInvitationMap.containsKey(invitationId)) {
            return false;
        }
        UserBanquetInvitation inv = userBanquetInvitationMap.get(invitationId);
        if(!StringUtils.isNullOrEmpty(inv.getInfo()) && inv.getInfo().length() >= 5000){
            try{
                BanquetCrossInvitation invitation = JSON.parseObject(inv.getInfo(), BanquetCrossInvitation.class);
                ActivityInfo activityInfo = NormalActivityMgr.getRunningCrossBanquetRankActivity();
                if(ActivityMgr.activityInTime(activityInfo)){
                    invitation.setServerIdsStr(StringUtils.listToString(activityInfo.getServerIdList(), ","));
                    //入库
                    inv.setInfo(JSON.toJSONString(invitation));
                }else {
                    long serverId = ConfigHelper.getLong("serverId");
                    List<Long> serverList = CrossMarriageGroupMgr.getFeastPartyServerList(serverId);
                    invitation.setServerIdsStr(StringUtils.listToString(serverList, ","));
                    //入库
                    inv.setInfo(JSON.toJSONString(invitation));
                }
            }catch (Exception e){
                BanquetMgr.getLogger().error("checkUserInvitation 转换失败", e);
                return false;
            }
            if(inv.getInfo().length() >= 5000){
                BanquetMgr.getLogger().info("checkUserInvitation 类型5的帖子范围过大，不让开宴会");
                return false;
            }
        }
        if (BanquetConfigMgr.isCrossBanquet(type)) {
            if (inv.getType() != eBanquetInvitationType.CrossBanquet1Invitation.getValue() &&
                    inv.getType() != eBanquetInvitationType.CrossBanquet2Invitation.getValue() &&
                    inv.getType() != eBanquetInvitationType.CrossBanquet3Invitation.getValue()) {
                return false;
            }
        }
        if (type == eBanquetInfoType.MarryBanquet.getValue()) {
            if (inv.getType() != eBanquetInvitationType.MarryInvitation.getValue()) {
                return false;
            }
        }
        if (type == eBanquetInfoType.ChildBanquet.getValue()) {
            if (inv.getType() != eBanquetInvitationType.ChildInvitation.getValue()) {
                return false;
            }
        }
        if (type == eBanquetInfoType.EstateBanquet.getValue()) {
            if (inv.getType() != eBanquetInvitationType.EstateInvitation.getValue()) {
                return false;
            }
        }
        if (inv.getOverTime() < System.currentTimeMillis() || inv.isUsed()) {
            return false;
        }
        return true;
    }

    //校验请帖是不是过期或者被使用
    public String useUserInvitation(String invitationId, int type) {
        if (!checkUserInvitation(invitationId, type)) {
            return "";
        }
        UserBanquetInvitation inv = userBanquetInvitationMap.get(invitationId);
        inv.setUsed(true);
        inv.setUseTime(System.currentTimeMillis());
        return inv.getInfo();
    }

    public UserBanquetInvitation getUserInvitationInfo(String invitationId) {
        if (userBanquetInvitationMap.containsKey(invitationId)) {
            return userBanquetInvitationMap.get(invitationId);
        }
        return null;
    }

    //过滤掉已经使用过和过期的请帖
    private Map<String, UserBanquetInvitation> removeOverTimeInvitation() {
        Map<String, UserBanquetInvitation> newList = new ConcurrentHashMap<>();
        for (UserBanquetInvitation userBanquetInvitation : allUserBanquetInvitationMap.values()) {
            if (userBanquetInvitation.getOverTime() > System.currentTimeMillis() && !userBanquetInvitation.isUsed()) {
                newList.put(userBanquetInvitation.getiId(), userBanquetInvitation);
            }
        }
        userBanquetInvitationMap = newList;
        return userBanquetInvitationMap;
    }

    //y用戶獲得請帖的時候同步給客戶端
    private void syncInvitation(UserBanquetInvitation userBanquetInvitation) {
        Map<String, UserBanquetInvitation> userBanquetInvitationMap = new ConcurrentHashMap<>();
        userBanquetInvitationMap.put(userBanquetInvitation.getiId(), userBanquetInvitation);
        BanquetProto.BanquetInvitationSync.Builder respMsg = BanquetPb.parseBanquetInvitationSyncMsg(userBanquetInvitationMap);
        player.sendPacket(Protocol.U_BANQUET_INVITATION_SYNC, respMsg);
    }

    //獲取用戶的所有請帖
    public Map<String, UserBanquetInvitation> getUserBanquetInvitationMap() {
        return removeOverTimeInvitation();
    }

    //是否跨服請帖，跨服輕鐵可以存在内容一致的
    private boolean isCrossBanquetInvitation(int type) {
        if (type == eBanquetInvitationType.CrossBanquet1Invitation.getValue()
                || type == eBanquetInvitationType.CrossBanquet2Invitation.getValue()
                || type == eBanquetInvitationType.CrossBanquet3Invitation.getValue()) {
            return true;
        }
        return false;
    }

    //生成用戶請帖
    public boolean makeInvitation(int type, String info) {
        //跨服请帖是可以重复内容的
        if (!isCrossBanquetInvitation(type) && type != eBanquetInvitationType.CrossBirthdayInvitation.getValue()) {
            for (UserBanquetInvitation old : allUserBanquetInvitationMap.values()) {
                if (old.getInfo().equals(info) && type == old.getType()) {
                    return false;
                }
            }
        }

        UserBanquetInvitation data = new UserBanquetInvitation();
        data.setiId(UUIDHelper.randomUUID(String.valueOf(GameServer.getInstance().getServerId())));//生成唯一id，和uid公用
        data.setUserId(getUserId());
        data.setType(type);
        data.setInfo(info);
        data.setCreateTime(System.currentTimeMillis());
        //跨服宴会帖子没有过期时间的，加100年
        if (isCrossBanquetInvitation(type)) {
            data.setOverTime(System.currentTimeMillis() + BanquetConfigMgr.getInvitationOverTime(type) * 1000 + 3153600000000L);
        } else {
            data.setOverTime(System.currentTimeMillis() + BanquetConfigMgr.getInvitationOverTime(type) * 1000);
        }
        if (type == eBanquetInvitationType.CrossBirthdayInvitation.getValue()){
            data.setOverTime(DateHelper.getTodayZeroTimeStamp() + DateHelper.DAY_MILLIONS);
        }
        data.setUsed(false);
        data.setInsertOption();

        allUserBanquetInvitationMap.put(data.getiId(), data);
        userBanquetInvitationMap.put(data.getiId(), data);
        syncInvitation(data);
        return true;
    }

    //登陸同步請帖
    private void loginSyncInvitation() {
        BanquetProto.BanquetInvitationSync.Builder msg = BanquetPb.parseBanquetInvitationSyncMsg(getUserBanquetInvitationMap());
        player.sendPacket(Protocol.U_BANQUET_INVITATION, msg);
    }

    @Override
    public boolean afterLoadData() {
        return true;
    }

    @Override
    public void afterLogin() {
        CrossBanquetAutoOpenMgr.syncAutoBanquetSettingInfo(player);
    }

    @Override
    public boolean saveData() {
        for (UserBanquetInvitation data : allUserBanquetInvitationMap.values()) {
            if (data.isInsertOption()) {
                UserBanquetInvitationBussiness.addUserBanquetInvitation(data);
            } else if (data.isUpdateOption()) {
                UserBanquetInvitationBussiness.updateUserBanquetInvitation(data);
            }
        }
        for (UserBanquetRecord data : userBanquetRecordMap.values()) {
            if (data.isInsertOption()) {
                UserBanquetBussiness.addUserBanquetRecord(data);
            }
        }
        for (UserBanquetRecord data : userCrossBanquetRecordMap.values()) {
            if (data.isInsertOption()) {
                UserBanquetBussiness.addUserBanquetRecord(data);
            }
        }

        for (Map<Integer, UserBanquetFeastReward> rewardMap : userBanquetFeastRewardMap.values()) {
            for (UserBanquetFeastReward reward : rewardMap.values()) {
                if (reward.getOp() == DataStatus.Insert) {
                    UserBanquetBussiness.addFeastBanquetReward(reward);
                } else if (reward.getOp() == DataStatus.Update) {
                    UserBanquetBussiness.updateFeastBanquetReward(reward);
                }
            }
        }

        for (UserBanquetSetting data : userBanquetSettingMap.values()) {
            if (data.isInsertOption()) {
                UserBanquetBussiness.addUserBanquetSetting(data);
            } else if (data.isUpdateOption()) {
                UserBanquetBussiness.updateUserBanquetSetting(data);
            }
        }

        return true;
    }

    //本服宴會人氣禮同步
    public void banquetPopRewardSync(UserBanquetData banquetData) {
        Map<String, Map<Integer, UserBanquetFeastReward>> banquetRewardMap = getUserBanquetFeastReward(banquetData);
        BanquetProto.BanquetPopRewardSync.Builder respMsg = BanquetPb.parseBanquetFeastRewardListResp(banquetRewardMap, eBanquetType.ServerFeastBanquet.getValue(), true);
        player.sendPacket(Protocol.U_BANQUET_FEAST_REWARD_SYNC, respMsg);
    }

    //跨服宴會人氣禮同步
    public void crossBanquetPopRewardSync(UserCrossBanquetData banquetData) {
        Map<String, Map<Integer, UserBanquetFeastReward>> banquetRewardMap = getCrossBanquetPopReward(banquetData);
        BanquetProto.BanquetPopRewardSync.Builder respMsg = BanquetPb.parseBanquetFeastRewardListResp(banquetRewardMap, eBanquetType.CrossBanquet.getValue(), true);
        player.sendPacket(Protocol.U_BANQUET_CROSS_POP_REWARD_SYNC, respMsg);
    }

    //人氣禮登陸同步
    private void banquetPopRewardAllSync() {
        Map<String, Map<Integer, UserBanquetFeastReward>> banquetRewardMap = getUserBanquetFeastRewardList();
        BanquetProto.BanquetPopRewardSync.Builder respMsg = BanquetPb.parseBanquetFeastRewardListResp(banquetRewardMap, eBanquetType.ServerFeastBanquet.getValue(), true);
        player.sendPacket(Protocol.U_BANQUET_FEAST_REWARD_SYNC, respMsg);
        Map<String, Map<Integer, UserBanquetFeastReward>> CrossBanquetRewardMap = getCrossBanquetPopRewardList();
        respMsg = BanquetPb.parseBanquetFeastRewardListResp(CrossBanquetRewardMap, eBanquetType.CrossBanquet.getValue(), true);
        player.sendPacket(Protocol.U_BANQUET_CROSS_POP_REWARD_SYNC, respMsg);
    }

    @Override
    public void loginSendMsg() {
        banquetPopRewardAllSync();
        loginSyncInvitation();
        BanquetMgr.syncBanquetFeast(player);
        BanquetMgr.syncSelfBanquet(player, null);
        CrossBanquetMgr.syncCrossBanquet(player);
        CrossBanquetMgr.syncSelfCrossBanquet(player, null);
        CrossBanquetMgr.syncCrossGoodBanquet(player);
        syncAutoInfo();
    }

    public String getCrossBanquetInvitationReward(String rewardStr, int activityId) {
        try {
            BaseActivityData baseActivityData = player.getModule(ActivityModule.class).getBaseActivityData(activityId);
            if (baseActivityData == null) {
                return "";
            }
            if(baseActivityData.getActivityInfo().getType() == eActivityType.FestivalGift.getValue()) {//自选礼包活动，宴会帖用在开的宴会区服范围
                ActivityInfo activityInfo = NormalActivityMgr.getExistCrossBanquetRankActivity();
                if (activityInfo != null) {
                    return getCrossBanquetInvitationReward(rewardStr, activityInfo.getServerListStr());
                }else {
                    return "";
                }
            }else {
                return getCrossBanquetInvitationReward(rewardStr, baseActivityData.getActivityInfo().getServerListStr());
            }
        } catch (Exception ex) {
            log.error(ex.toString());
        }
        return "";
    }

    //获取特殊的奖励(如跨服宴会请帖)
    public String getCrossBanquetInvitationReward(String rewardStr,String serverList) {
        if(StringUtils.isNullOrEmpty(rewardStr)){
            return "";
        }
        Property reward = PropertyHelper.parseStringToProperty(rewardStr);
        BanquetCrossInvitation inv = new BanquetCrossInvitation();

        // 设置区服ID
        String idsStr = calcServerIdsStr(serverList);
        inv.setServerIdsStr(idsStr);

        int num1 = reward.getCountByGoodsId(GameConfig.BANQUET_CROSS_INVITATION_1).intValue();
        if (num1 > 0) {
            reward.removeProperty(GameConfig.BANQUET_CROSS_INVITATION_1, BigInteger.valueOf(num1));
            for (int i = 0; i < num1; i++) {
                makeInvitation(eBanquetInvitationType.CrossBanquet1Invitation.getValue(), JSON.toJSONString(inv));
            }
        }
        int num2 = reward.getCountByGoodsId(GameConfig.BANQUET_CROSS_INVITATION_2).intValue();
        if (num2 > 0) {
            reward.removeProperty(GameConfig.BANQUET_CROSS_INVITATION_2, BigInteger.valueOf(num2));
            for (int i = 0; i < num2; i++) {
                makeInvitation(eBanquetInvitationType.CrossBanquet2Invitation.getValue(), JSON.toJSONString(inv));
            }
        }
        int num3 = reward.getCountByGoodsId(GameConfig.BANQUET_CROSS_INVITATION_3).intValue();
        if (num3 > 0) {
            reward.removeProperty(GameConfig.BANQUET_CROSS_INVITATION_3, BigInteger.valueOf(num3));
            for (int i = 0; i < num3; i++) {
                makeInvitation(eBanquetInvitationType.CrossBanquet3Invitation.getValue(), JSON.toJSONString(inv));
            }
        }
        return PropertyHelper.parsePropertyToString(reward);
    }

    private String calcServerIdsStr(String serverList) {
        long serverId = GameServer.getInstance().getServerId();
        Set<Long> crossIds = new HashSet<>();
        Set<Long> areaIds = new HashSet<>(); // 目前不发跨地区服务器

        if (!StringUtils.isNullOrEmpty(serverList)) {
            int channelId = ServerListMgr.getChannelId(serverId);
            for (long tmpServerId : StringUtils.stringToLongList(serverList, ",")) {
                if (tmpServerId == serverId) {
                    continue; // 本服
                }
                if (channelId == ServerListMgr.getChannelId(tmpServerId)) {
                    crossIds.add(tmpServerId); // 跨服
                } else {
                    areaIds.add(tmpServerId); // 跨地区
                }
            }
        }

        List<Long> ids = new ArrayList<>();
        ids.add(serverId);
        ids.addAll(crossIds);
        return StringUtils.listToString(ids, ",");
    }

    public String getUserBanquetSettingGiftTypeAccept(int type) {
        if (userBanquetSettingMap.containsKey(type)) {
            return userBanquetSettingMap.get(type).getGiftTypeAccept();
        } else {
            return "";
        }
    }

    public String getUserBanquetSettingBanquetId(int type) {
        if (userBanquetSettingMap.containsKey(type)) {
            return userBanquetSettingMap.get(type).getBanquetId();
        } else {
            return "";
        }
    }

    public void updateUserBanquetSetting(int type, String giftTypeAccept, String banquetId) {
        if (userBanquetSettingMap.containsKey(type)) {
            UserBanquetSetting setting = userBanquetSettingMap.get(type);
            setting.setGiftTypeAccept(giftTypeAccept);
            setting.setUpdateTime(DateHelper.getCurrentTime());
            setting.setBanquetId(banquetId);
        } else {
            UserBanquetSetting setting = new UserBanquetSetting(player.getUserId(), type, giftTypeAccept, DateHelper.getCurrentTime());
            setting.setInsertOption();
            setting.setBanquetId(banquetId);
            userBanquetSettingMap.put(type, setting);
        }
    }

    public void updateUserBanquetSetting(int type, String giftTypeAccept) {
        if (userBanquetSettingMap.containsKey(type)) {
            UserBanquetSetting setting = userBanquetSettingMap.get(type);
            setting.setGiftTypeAccept(giftTypeAccept);
            setting.setUpdateTime(DateHelper.getCurrentTime());
        } else {
            UserBanquetSetting setting = new UserBanquetSetting(player.getUserId(), type, giftTypeAccept, DateHelper.getCurrentTime());
            setting.setInsertOption();
            userBanquetSettingMap.put(type, setting);
        }
    }

    public void updateUserBanquetSettingBanquetId(int type, String banquetId) {
        if (userBanquetSettingMap.containsKey(type)) {
            UserBanquetSetting setting = userBanquetSettingMap.get(type);
            setting.setBanquetId(banquetId);
        } else {
            UserBanquetSetting setting = new UserBanquetSetting(player.getUserId(), type, "", DateHelper.getCurrentTime());
            setting.setInsertOption();
            setting.setBanquetId(banquetId);
            userBanquetSettingMap.put(type, setting);
        }
    }

    public boolean settingCanReset(int type, long activityBeginTIme) {
        if (userBanquetSettingMap.containsKey(type)) {
            UserBanquetSetting setting = userBanquetSettingMap.get(type);
            if (setting.getUpdateTime()/1000 >= activityBeginTIme) {
                return false;
            }
        }
        return true;
    }

    //看看有没有开跨服争霸，有就同步下
    public void syncAutoInfo(){
        ActivityInfo crbAcInfo = NormalActivityMgr.getShowingCrossBanquetRankActivity();
        //有跨服争霸，请求同步下自动设置
        if(crbAcInfo != null){
            CrossBanquetProto.CrossBanquetAutoSetSyncReq.Builder reqMsg = CrossBanquetProto.CrossBanquetAutoSetSyncReq.newBuilder();
            reqMsg.setAcId(crbAcInfo.getActivityId());
            TitleInfo titleInfo = TitleMgr.getTitleInfo(player.getTitleId());
            int titleAdd = titleInfo.getBanquetEffect();
            int skillAdd = BanquetMgr.getBanquetJoinSkillAddition(player);
            reqMsg.setSkillAdd(skillAdd);
            reqMsg.setTitleAdd(titleAdd);
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.C_CROSS_BANQUET_AUTO_SYNC, reqMsg);
            GamePlayerMgr.sendPacket(player.getUserId(), pbMsg);
        }
    }

    public void sendGetAutoPopReward(){
        ActivityInfo crbAcInfo = NormalActivityMgr.getRunningCrossBanquetRankActivity();
        if(crbAcInfo != null){
            CrossBanquetProto.CrossAddAutoBanquetPopRewardReq.Builder reqMsg = CrossBanquetProto.CrossAddAutoBanquetPopRewardReq.newBuilder();
            reqMsg.setAcId(crbAcInfo.getActivityId());
            reqMsg.setUserId(player.getUserId());
            YanQuMessage pbMsg = YanQuMessageUtils.buildMessage(Protocol.C_CROSS_BANQUET_AUTO_ADD_POPULARITY, reqMsg);
            GamePlayerMgr.sendPacket(player.getUserId(), pbMsg);
        }
    }
}
